import re
import json
import logging
import random

from django import http
from django.http import HttpResponse

from aijia_zufang.utils.response_code import RET
from apps.users.models import User
from django.views import View
from django_redis import get_redis_connection
# 实例化日志对象
from apps.verifications.libs.captcha.captcha import captcha

logger = logging.getLogger('django')



# 图片验证码
class ImageCodeView(View):
    def get(self, request):

        # 1. 获取传入的验证码编号
        cur = request.GET.get('cur')
        pre = request.GET.get('pre')

        # 2. 判断当前图片验证码是否有值,如果 cur 为 None 则返回参数有误响应
        if cur is None:
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': 'cur参数有误!'})

        # 3.1 生成图形验证码
        text, image = captcha.generate_captcha()
        # 3.2 保存图片验证码
        logger.info(text)

        # 4. 保存 uuid 编号和其对应的图片验证码内容到 redis 数据库的别名, 创建连接到 redis 的对象
        redis_conn = get_redis_connection('verify_code')
        if pre:
            # 4.1 删除之前存储的验证码图片
            redis_conn.delete('ImageCode_' + pre)
        # 4.2 设置图片验证码的过期时间
        redis_conn.setex('ImageCode_' + cur, 300, text)

        # 5. 返回验证码图片给前端,并设置返回的类型格式类型
        return HttpResponse(image, content_type = 'image/png')



# 短信验证码
class SMSCodeView(View):
    def post(self, request):

        # 1. 接受参数
        data_dict = json.loads(request.body.decode())
        mobile = data_dict.get('mobile')  # 手机号
        image_code = data_dict.get('image_code')  # 图片验证码
        image_code_id = data_dict.get('image_code_id')  # 图片验证码 UUID

        # 2. 校验参数是否齐全
        if not all([mobile, image_code, image_code_id]):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': '参数不齐全！'})

        # 3. 使用正则表达式校验手机号是否格式正确
        if not re.match('^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'errno': RET.PARAMERR, 'errmsg': '手机号码格式有误！'})

        # 4. 通过图片验证码的 UUID 去查询 redis 中的真是图片内容
        redis_conn = get_redis_connection('verify_code')
        # 4.1 如果能够取出值,就删除 redis 数据库中的内容
        try:
            real_image_code = redis_conn.get('ImageCode_' + image_code_id)
            if real_image_code:
                redis_conn.delete('ImageCode_' + image_code_id)
        # 4.2 如果上面的代码发生错误或者其他的可能,则做以下判断
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': '未知原因导致图片验证码获取失败！'})

        # 5. 判断图片验证码是否已经过期
        if not real_image_code:
            return http.JsonResponse({'errno': RET.NODATA, 'errmsg': '图片验证码已经过期！'})

        # 6. 判断输入的图片验证码是否有误(前端和redis数据库作对比),注意 redis 数据库去出来的是 bytes 二进制格式,需要转换成 str 字符串格式,并且允许使用 lower 大小写
        if image_code.lower() != real_image_code.decode().lower():
            return http.JsonResponse({'errno': RET.DATAERR, 'errmsg': '验证码输入错误！'})

        # 7. 校验该手机号是否已经注册
        try:
            user = User.objects.get(mobile = mobile)
        except Exception as e:
            user = None  # 如果查询时出现错误，也需要给user初始化，如果不初始化，会报未定义的异常
            logger.error(e)
        if user:
            return http.JsonResponse({'errno': RET.DATAEXIST, 'errmsg': '该手机号已经被注册！'})

        # 8. 生成发送短信的内容并发送短信(需要使用随机模块)
        sms_code = random.randint(100000, 999999)

        # 9. 在 redis 数据库中保存短信验证码的内容
        # 9.1 保存成功短信验证码 60 秒有效时间
        try:
            redis_conn.set("SMS_" + mobile, 300, sms_code)
        # 9.2 如果上述代码不执行的话则执行下面自定义错误报告
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'errno': RET.DBERR, 'errmsg': "保存短信验证码失败！"})

        # 10. 让第三方云通讯发短信
        from ronglian_sms_sdk import SmsSDK
        accId = '8a216da8797924980179b26d5780142e'
        accToken = '40e6fb162dde40ba848805d67c541b93'
        appId = '8a216da8797924980179b26d587a1434'
        # 10.1 调用发短信的函数,实例化云通讯对象
        sdk = SmsSDK(accId, accToken, appId)
        # 10.2 调用发短信的函数   短信模板id       手机号      短信验证码   过期时间  分钟
        resp = sdk.sendMessage(tid = '1', mobile = mobile, datas = (sms_code, 5))
        print(f'短信验证码是:{resp}', sms_code)

        # 11. 返回发送成功的响应报文
        return http.JsonResponse({'errno': RET.OK, 'errmsg': '短信验证码发送成功！'})
